package de.graph.document;

import java.util.Collection;
import java.util.HashMap;
import java.util.Set;

import de.graph.utils.UIDManager;

class DocumentImpl implements Document {

    private final Long id;

    private final HashMap<String, Object> properties;

    protected DocumentImpl() {
        this(UIDManager.createUID());
    }

    protected DocumentImpl(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("Parameter 'id' must not be null!");
        }

        this.id = id;
        this.properties = new HashMap<String, Object>();

        DocumentManager.getInstance().registerProperties(this);
    }

    @SuppressWarnings("unchecked")
    public <ValueType> ValueType getProperty(String name) {
        return (ValueType) properties.get(name);
    }

    @SuppressWarnings("unchecked")
    public <ValueType> ValueType getProperty(String name, ValueType defaultValue) {
        ValueType value = (ValueType) properties.get(name);
        if (value == null) {
            return defaultValue;
        }

        return value;
    }

    public <ValueType> void setProperty(String name, ValueType value) {
        if (name == null || value == null) {
            return;
        }

        properties.put(name, value);
    }

    @SuppressWarnings("unchecked")
    public <ValueType> ValueType removeProperty(String name) {
        return (ValueType) properties.remove(name);
    }

    public Set<String> getPropertyKeys() {
        return properties.keySet();
    }

    public Collection<Object> getPropertyValues() {
        return properties.values();
    }

    @SuppressWarnings("unchecked")
    public <ValueType> Collection<ValueType> getPropertyValues(Class<ValueType> typeClass) {
        return (Collection<ValueType>) properties.values();
    }

    public void clear() {
        DocumentManager.getInstance().unregisterProperties(this);

        properties.clear();
    }

    public Long getId() {
        return id;
    }

    @Override
    public int hashCode() {
        return getId().hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (obj == null) {
            return false;
        }

        if (!(obj instanceof DocumentImpl)) {
            return false;
        }

        DocumentImpl other = (DocumentImpl) obj;

        return getId().equals(other.getId());
    }

    @Override
    public String toString() {
        return properties.toString();
    }
}
